#| dummy.lsp Copyright (c) 1999 by Pedro Valero
Version 1: January 
adds a command to the transformations menu that transforms a 
variable into a set of binary variables for each value of the variable. 
It works with category variables (which is obviously the most 
important case) and numeric. It has a known problem. When the file 
only has category variables I get the error:
Version 2, January 25, 1998. modified to avoid naming conflict.
You were right. The file dummy had a conflict defining a funcion which
existed previously. The following seems to work right with multivariate
data files. Does not work with category variables. I do not why yet.

Error: illegal zero argument
Happened in: #<Subr-/: #115aa78>
|#


(defun dummy-coding  (&key 
   (data     current-data)
   (dialog     nil)
   (name       "Dummy")
   (title      nil))
"Codes values in vars as dummy, 0-1, variables. Puts names to variables
and adds a new dataset. Useful for regression analysis and missing data
imputation."
;(trace :new :isnew)
   (send dummy-transf-object-proto :new 9 data title name dialog '(all)))


(defun dummy-code  (&key 
   (data     current-data)
   (dialog     nil)
   (name       "Dummy")
   (title      nil))
"Codes values in vars as dummy, 0-1, variables. Puts names to variables
and adds a new dataset. Useful for regression analysis and missing data
imputation."
;(trace :new :isnew)
   (send dummy-transf-object-proto :new 9 data title name dialog '(all)))


(defproto dummy-transf-object-proto '() () transf-object-proto)

(defmeth dummy-transf-object-proto :isnew (&rest args)
  (apply #'call-next-method args)
  )

(defmeth dummy-transf-object-proto :options () t)

(defmeth dummy-transf-object-proto :analysis ()
  (let* (
         (data-matrix (send current-data :active-data-matrix '(category)))
         (dummy-variables (names-variables-dummy (send current-data
                                                       :active-variables '(category))
                                                 (values-in-vars data-matrix)))
         (dummy-data-matrix (if dummy-variables
                                (matrix-dummy-var (list-dummy-var data-matrix))
                                (error-message "No categorical variables in the dataset")))

         )
(when dummy-variables
    (data (send self :name)
          :created   (- (send *desktop* :num-icons) 1)
          :title     (concatenate 'string "Dummy-" (send self :title))
          :labels    (send current-data :active-labels) 
          :data      (combine dummy-data-matrix)
          :variables dummy-variables
          ;:types     (send self :active-types     '(all))
          ))
 )
    )

; Funciones para cambiar una variable en una serie de variables ficticias
; para cada uno de sus valores. Importante para anlisis de regresin claro

(defun values-in-vars (matrix)
  "Obtiene una lista con los valores para cada una de las variables de una
matriz"
    (let ((matrix (column-list matrix))
          )
      (map-elements 'remove-duplicates (map-elements 'coerce matrix 'list)
:test 'equal)
      ))


(defun dummy-var (var values)
   "Produce una lista de listas con variables ficticias para los valores de
una variable. Necesita la variable y la lista de valores"
  (let* ((values values)
         (var (coerce var 'list))
         (numvalues (length values))
         (result nil)
         )
      (dotimes (i numvalues)    
               (setf result 
                     (append result 
                             (list (map-elements 'compare (select values i) var)))))
    result ))

(defun compare (x y)
  "Args: (x y) Changes the value in a variable for one and the rest for zero"
  (if (equal x y) 1 0))
                      
(defun list-dummy-var (matrix)
  "Aplica dummy-var a matrices as que se obtiene una lista de listas de
listas de variables ficticias"
  (let*
    (
     (matrix matrix)
     (values-list (values-in-vars matrix))
    
    )
    
    (map-elements 'dummy-var (column-list matrix) values-list)
    
    ))


(defun names-variables-dummy (variables values)
"Args: (variables values)"
  (let ( (variables variables)
         (values values)
         (numvariables (length variables))
         (result nil) )
    (dotimes (i numvariables)
             (setf result (append result (map-elements 'concatenate 
                  'string  (select variables i) "-" 
                  (map-elements  'princ-to-string (select values i))))))
    result))


(defun matrix-dummy-var (list-dummy-var)
  (let* ( (list-dummy-var list-dummy-var)
          (ncols (reduce #'+ (map-elements 'length list-dummy-var)))
          (nrows (length (first (first list-dummy-var)))))
    (transpose (make-array (list ncols nrows) 
                           :initial-contents (combine list-dummy-var)))))
